package br.ufrj.ppgi.infovis.mtgraph;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import java.io.*;
import java.nio.*;
import java.nio.charset.*;
import java.util.HashMap;
import java.util.Map;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.*;

import org.mt4j.MTApplication;
import org.mt4j.components.TransformSpace;
import org.mt4j.components.bounds.IBoundingShape;
import org.mt4j.components.visibleComponents.shapes.MTRectangle;
import org.mt4j.components.visibleComponents.shapes.MTRectangle.PositionAnchor;
import org.mt4j.components.visibleComponents.widgets.MTTextArea;
import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapEvent;
import org.mt4j.util.MTColor;
import org.mt4j.util.font.FontManager;
import org.mt4j.util.font.IFont;
import org.mt4j.util.math.Vector3D;

import processing.core.PImage;

import br.ufrj.ppgi.infovis.StartInfoVis;
import br.ufrj.ppgi.infovis.forms.AbstractOverlayDefaultList;
import br.ufrj.ppgi.infovis.forms.OverlayListLoadGraph;
import br.ufrj.ppgi.infovis.styles.Category;
import br.ufrj.ppgi.infovis.styles.Configuration;
import br.ufrj.ppgi.infovis.toolbar.*;
import br.ufrj.ppgi.infovis.util.TextureCache;
import br.ufrj.ppgi.infovis.util.XMLExport;
import br.ufrj.ppgi.infovis.util.XMLImport;


public class GraphToolBar {

    public static final float button_size = 60;

    private GraphScene scene;
    private MTLayoutContainer buttonContainerLeft;
    private MTLayoutContainer buttonContainerRight;
    MTApplication app;
    
	final boolean jOption = false;
    
	public GraphToolBar(GraphScene scene){
		this.scene = scene;
		
		app = (MTApplication) scene.getMTApplication();
		initialize();		
	}
	
	//Create one MTLayoutContainer for the main icons
	private void initialize() {
		this.buttonContainerLeft = new MTLayoutContainer(MTLayoutContainer.ALIGN_LEFT, MTLayoutContainer.LAYOUT_VERTICAL, (MTApplication) scene.getMTApplication(), 30f);
		this.buttonContainerLeft.setName("ToolBarLeft");
		this.buttonContainerRight = new MTLayoutContainer(MTLayoutContainer.ALIGN_RIGHT, MTLayoutContainer.LAYOUT_VERTICAL, (MTApplication) scene.getMTApplication(), 10f);
		this.buttonContainerRight.setName("ToolBarRigth");
		
	}
	
	//Adiciona o Toolbar em GraphScene 
	private void refreshToScene() {
		this.scene.getCanvas().addChild(this.buttonContainerLeft);
		//this.buttonContainerLeft.setAnchor(PositionAnchor.UPPER_LEFT);
		//this.buttonContainerLeft.setPositionGlobal(new Vector3D().ZERO_VECTOR);
		//this.buttonContainer.setHeightXYGlobal(scene.getMTApplication().height);
		//this.buttonContainerRight.setNoStroke(true);
		this.scene.getCanvas().addChild(this.buttonContainerRight);
	}
	
	//Adiciona os botoes basicos no Cenario
	public void AddDefaultButtons(){
		
		//Configuration config;
		
		Category[] categories = scene.getConfig().getCategories();
		
		for (Category cat : categories){			
			this.AddButtonNewNode(cat);
			
		}
		
		this.AddButtonLinkNode();
		this.AddButtonUnlinkNode();
		this.addSpacer();
		this.AddButtonOrganizeNodes();
		this.AddButtonDeleteNode();
		this.addSpacer();
		this.AddButtonExport();
		this.AddButtonImport();

		this.refreshToScene();
	}


//------------------------------------------------------------------------------------
//--------------------------------LEFT------------------------------------------------
//------------------------------------------------------------------------------------

	public void addSpacer(){
		MTRectangle mtr = new MTRectangle(scene.getMTApplication(),0,0);
		
		mtr.setNoStroke(true);
		mtr.setNoFill(true);
		mtr.setPickable(false);
		
		buttonContainerRight.addChild(mtr);
	}
	
	
	
	
	//Cria um botao de Adicionar Nos
	public void AddButtonNewNode(final Category cat) {
		//add a button with  action listener assigned
		
		Vector3D pos = new Vector3D();
		
		
		final MTToolbarButtonWithLabel tbb = new MTToolbarButtonWithLabel(
				TextureCache.getTexture(TextureCache.BTN_ADD), 
				app, cat.getName(), cat.getColor());
		tbb.setFillColor(cat.getColor());
		
		tbb.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				switch(event.getID()) {
					case TapEvent.TAPPED:
						NewNodeEvent(cat);
					break;
				}
			}
	    });

		tbb.rotateZ(new Vector3D(0,0), 90);
		tbb.setSizeXYGlobal(button_size, button_size);
		buttonContainerLeft.addChild(tbb);
	}
	
	//Chama evento para criar um No em GraphScene
	private void NewNodeEvent(Category cat)  {
		//Deseleciono os nos
		this.scene.deselectionNodes();
		this.scene.NewNode(cat);
	}


	
//------------------------------------------------------------------------------------
//--------------------------------RIGHT-----------------------------------------------
//------------------------------------------------------------------------------------
	
	public void AddButtonLinkNode() {
		final MTToolbarButton tbb = new MTToolbarButton(TextureCache.getTexture(TextureCache.BTN_LINK),app);
		tbb.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
			
				switch(event.getID()) {
					case TapEvent.TAPPED:
					try {
						LinkNodeEvent(tbb);
					} catch (GraphException e) {
						e.printStackTrace();
					}
					break;
				}
			}
	    });
		tbb.rotateZ(new Vector3D(0,0), -90);
		tbb.setSizeXYGlobal(button_size, button_size);
		buttonContainerRight.addChild(tbb);		
	}
	
	private void LinkNodeEvent(MTToolbarButton tbb ) throws GraphException {
		//Deseleciono os nos
		this.scene.deselectionNodes();
		tbb.setFillColor(MTColor.RED);
		scene.setClickedTBB(tbb);
		
		//Habilito para criacao da aresta
		this.scene.setEventLinkNode();
		this.scene.setSelectionEvent(true);
		//tbb.setFillColor(new MTColor(255,255,255,255));
	}
	
	
	public void AddButtonUnlinkNode() {
		final MTToolbarButton tbb = new MTToolbarButton(TextureCache.getTexture(TextureCache.BTN_UNLINK), app);
		tbb.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				switch(event.getID()) {
					case TapEvent.TAPPED:
					try {
						UnlinkNodeEvent(tbb);
					} catch (Exception e) {
						e.printStackTrace();
					}
					break;
				}
			}
	    });
		tbb.rotateZ(new Vector3D(0,0), -90);
		tbb.setSizeXYGlobal(button_size, button_size);
		buttonContainerRight.addChild(tbb);		
	}
	
	private void UnlinkNodeEvent(MTToolbarButton tbb) {
		//Deseleciono os nos
		this.scene.deselectionNodes();
		tbb.setFillColor(MTColor.RED);
		//tbb.setTexture(TextureCache.getTexture(TextureCache.BTN_IMPORT));
		
		scene.setClickedTBB(tbb);
		//Habilito para remocao da aresta
		this.scene.setEventUnlinkNode();
		this.scene.setSelectionEvent(true);		
	}	
	

	public void AddButtonOrganizeNodes() {
		final MTToolbarButton tbb = new MTToolbarButton(TextureCache.getTexture(TextureCache.BTN_ORGANIZE), app);
		tbb.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				switch(event.getID()) {
					case TapEvent.TAPPED:
					try {
						OrganizeNodesEvent();
					} catch (Exception e) {
						e.printStackTrace();
					}
					break;
				}
			}
	    });
		tbb.rotateZ(new Vector3D(0,0), -90);
		tbb.setSizeXYGlobal(button_size, button_size);
		buttonContainerRight.addChild(tbb);
	}	
	
	private void OrganizeNodesEvent() {
		//todo
		this.scene.getGraph().updateAll();
		System.out.println("TODO");
	}
	

	//Cria um botao de Deletar Nos
	public void AddButtonDeleteNode() {
	
		final MTToolbarButton tbb = new MTToolbarButton(TextureCache.getTexture(TextureCache.BTN_DELETE), app);
		tbb.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				switch(event.getID()) {
					case TapEvent.TAPPED:
						DeleteNodeEvent(jOption);
					break;
				}
			}
	    });
		tbb.rotateZ(new Vector3D(0,0), -90);
		tbb.setSizeXYGlobal(button_size, button_size);
		buttonContainerRight.addChild(tbb);
	}
	

	private void DeleteNodeEvent(boolean pergunta)  {
		/*
		 *  pergunta | resp  |         valor
		 * --------------------------------------------
		 *   true	 | yes	 | (false OR true) = apaga				
		 *   true	 |  no   | (false OR false) = nao apaga
		 *  false	 |  no   | (true  OR *false) = apaga
		 */
			
		int resp = 0;		
		if (pergunta) {
			resp = JOptionPane.showConfirmDialog(null,
					"Remover todos os n�s do grafo?", "Remover n�s?",
					JOptionPane.YES_NO_OPTION);
		} 
		if (!pergunta || resp == 0) {
			//Deseleciono os nos
			this.scene.deselectionNodes();
			this.scene.DeleteNode(true, null);
		}
	}
	

	public void AddButtonExport() {
		final MTToolbarButton tbb = new MTToolbarButton(TextureCache.getTexture(TextureCache.BTN_EXPORT), app);
		tbb.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				switch(event.getID()) {
					case TapEvent.TAPPED:
						ExportEvent();
					break;
				}
			}
	    });
		tbb.rotateZ(new Vector3D(0,0), -90);
		tbb.setSizeXYGlobal(button_size, button_size);
		buttonContainerRight.addChild(tbb);		
	}
	
	private void ExportEvent() {
		XMLExport exporter = new XMLExport(scene.getGraph());
		exporter.Export();
	}
	
	
	public void AddButtonImport() {
		final MTToolbarButton tbb = new MTToolbarButton(TextureCache.getTexture(TextureCache.BTN_IMPORT),app);
		tbb.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				switch(event.getID()) {
					case TapEvent.TAPPED:
						ImportEvent(jOption);						
					break;
				}
			}
	    });
		tbb.rotateZ(new Vector3D(0,0), -90);
		tbb.setSizeXYGlobal(button_size, button_size);
		buttonContainerRight.addChild(tbb);
	}
	
	private void ImportEvent(boolean jOption) {
		String file_name = "src/br/ufrj/ppgi/infovis/data/xml/dados.xml";
		if (jOption) {
			final JFileChooser fc = new JFileChooser();
			int returnVal = fc.showOpenDialog(null);
			if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
				java.io.File file = fc.getSelectedFile();
				file_name = file.toString();
				DeleteNodeEvent(false);
			}
			this.Import(file_name, jOption);
		} else {		
			//OVERLAY FORMS
	        // Get the size factor by which to calculate the width and height
	        float sizeFactorOverlayList = (this.scene.getMTApplication().getWidth() / AbstractOverlayDefaultList.OVERLAY_WIDTH_MAX) * AbstractOverlayDefaultList.OVERLAY_WIDTH_SCALE_TO_APP_PERCENT;
	        // Create overlay
	        OverlayListLoadGraph loadGraphForm = new OverlayListLoadGraph(
	                this.scene.getMTApplication(), this.scene, 0, 0,
	                AbstractOverlayDefaultList.OVERLAY_WIDTH_MAX * sizeFactorOverlayList,
	                AbstractOverlayDefaultList.OVERLAY_HEIGHT_MAX * sizeFactorOverlayList,
	                FontManager.getInstance().createFont(this.scene.getMTApplication(),AbstractOverlayDefaultList.HEADLINE_FONT_FILE_NAME,AbstractOverlayDefaultList.HEADLINE_FONT_SIZE, MTColor.BLACK,true),
	                FontManager.getInstance().createFont(this.scene.getMTApplication(),AbstractOverlayDefaultList.LIST_CONTENT_FONT_BIG_FILE_NAME,AbstractOverlayDefaultList.LIST_CONTENT_FONT_BIG_SIZE,MTColor.BLACK, true),
	                FontManager.getInstance().createFont(this.scene.getMTApplication(),AbstractOverlayDefaultList.LIST_CONTENT_FONT_SMALL_FILE_NAME,AbstractOverlayDefaultList.LIST_CONTENT_FONT_SMALL_SIZE,MTColor.BLACK, true)
	         );
	        // Re-position
	        loadGraphForm.setPositionGlobal(new Vector3D(this.scene.getMTApplication().width/2f, this.scene.getMTApplication().height/2f));
	        // Add to canvas
	        this.scene.getCanvas().addChild(loadGraphForm);
		}
	}
	
	public void Import(String file, boolean option) {
        DeleteNodeEvent(option);
		XMLImport importer = new XMLImport(StartInfoVis.getGraphScene(), file);
		importer.Import();		
	}
}
